using GameBaseFramework.Base;
using GameBaseFramework.Commands;
using GameBaseFramework.Pattern;
using GameGraphics;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace GameBaseFramework.Network
{
    public class NetworkManager
    {
        private static NetworkManager _Instance;

        /// <summary>
        /// 单例访问
        /// </summary>
        public static NetworkManager Instance
        {
            get
            {
                if (_Instance == null) _Instance = new();
                return _Instance;
            }
        }

        /// <summary>
        /// 本客户端socket
        /// </summary>
        private Socket socket;

        /// <summary>
        /// 是否已经与服务器进行了连接
        /// </summary>
        private bool isConnect;

        /// <summary>
        /// 发送队列
        /// </summary>
        private Queue<string> sendQueue = new Queue<string>();

        /// <summary>
        ///接收消息队列
        /// </summary>
        private Queue<string> receiveQueue = new Queue<string>();

        /// <summary>
        /// 存放收到消息的字节数组
        /// </summary>
        private byte[] receiveBytes = new byte[1024 * 1024];

        /// <summary>
        /// 发送线程信号量
        /// </summary>
        private AutoResetEvent SendEvent = new AutoResetEvent(false);

        /// <summary>
        /// 接收线程信号量
        /// </summary>
        private AutoResetEvent ReceiveEvent = new AutoResetEvent(false);

        /// <summary>
        /// 更新
        /// </summary>
        public void Update()
        {
            //如果收到消息队列中存在消息，则让UI更新面板
            if (receiveQueue.Count > 0)
            {
                Debug.Log(receiveQueue.Dequeue());
            }
        }

        /// <summary>
        /// 处理接收到信息的线程
        /// </summary>
        public void Receive_Thread(object obj)
        {
            while (isConnect)
            {
                ReceiveEvent.WaitOne();
                var Msg = receiveQueue.Dequeue();
                CommandManager.SendCommand<GetMessageCommand>(new GetMessageCommand() { Content = Msg });
            }
        }


        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="ip">服务器IP地址</param>
        /// <param name="port">服务器程序端口号</param>
        public void ConnectServer(string ip, int port)
        {
            //如果在连接状态，就不执行连接逻辑了
            if (isConnect)
                return;

            //避免重复创建socket
            if (socket == null)
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //连接服务器
            IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);

            try
            {
                socket.Connect(ipEndPoint);
            }
            catch (SocketException e)
            {
                DebugTool.LogException(e);
                return;
            }

            isConnect = true;

            //开启发送消息线程
            ThreadPool.QueueUserWorkItem(SendMsg_Thread);
            //开启接收消息线程
            ThreadPool.QueueUserWorkItem(ReceiveMsg_Thread);
            //处理消息线程
            ThreadPool.QueueUserWorkItem(Receive_Thread);

            
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="msg"></param>
        public void Send(string msg)
        {
            //将消息放入到消息队列中
            sendQueue.Enqueue(msg);
            SendEvent.Set();
        }

        /// <summary>
        /// 发送消息线程
        /// </summary>
        /// <param name="obj"></param>
        private void SendMsg_Thread(object obj)
        {
            while (isConnect)
            {
                SendEvent.WaitOne();
                socket.Send(Encoding.UTF8.GetBytes(sendQueue.Dequeue()));
            }
        }

        /// <summary>
        /// 接收消息线程
        /// </summary>
        /// <param name="obj"></param>
        private void ReceiveMsg_Thread(object obj)
        {
            int msgLength;
            while (isConnect)
            {
                //判断有没有收到消息
                if (socket.Available > 0)
                {
                    msgLength = socket.Receive(receiveBytes);
                    DebugTool.Log("接收到消息，长度为" + msgLength);
                    //收到消息，反序列化后放入收到消息队列中，在Update中不停检测有没有收到的消息，收到了就让UI更新面板
                    receiveQueue.Enqueue(Encoding.UTF8.GetString(receiveBytes, 0, msgLength));
                    ReceiveEvent.Set();
                }
            }
        }

        /// <summary>
        /// 释放连接
        /// </summary>
        public void Close()
        {
            if (socket != null && isConnect)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();

                isConnect = false;
            }
        }

        private void OnDestroy()
        {
            Close();
        }
    }



}

